<?php
/***
 * Candy框架 内存缓存Memcached类
 * 
 * $Author: 刘森 (fingerboy@qq.com) $
 * $Date: 2019-08-03 08:31:01 $   
 */
 
declare(strict_types=1);
namespace Candy\Extend\Cache\Driver;

defined('CANDY') OR die('You Are A Bad Guy. o_O???');
 
final Class Redis {
	protected $link = null;
    protected $config  = [
		'host'       => '127.0.0.1',	// redis主机
        'port'       => 6379,			// redis端口
        'password'   => '',				// 密码
        'select'     => 0,				// 操作库
        'timeout'    => 0,				// 超时时间(秒)
        'expire'     => 3600,			// 有效期(秒)
        'persistent' => false,			// 是否长连接
        'prefix'     => '',				// 前缀
	];	
	
	
    /**
	 *
     * @param array $config 
     * @access public
     */
    public function __construct(array $config = [])
	{
        if (!empty($config)) {
            $this->config = array_merge($this->config, $config);
        }
        $this->link = new \Redis();
        if ($this->config['persistent']) {
            $this->link->pconnect($this->config['host'], $this->config['port'], $this->config['timeout'], 'persistent_id_' . $this->config['select']);
        } else {
            $this->link->connect($this->config['host'], $this->config['port'], $this->config['timeout']);
        }

        if ('' != $this->config['password']) {
            $this->link->auth($this->config['password']);
        }

        if (0 != $this->config['select']) {
            $this->link->select($this->config['select']);
        }
    }
	
	/**
	 * 获取redis对象
	 *
	 * @return	object		redis对象
	 */
	public function getMem(): object
	{
		return $this->link;
	}
	
	/**
	 * 检查redis是否连接成功
	 * @return	bool	连接成功返回true,否则返回false
	 */
	public function cacheConnectError(): bool
	{
		$stats=$this->link->ping();
		if($stats === '+PONG'){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 添加key
	 *
	 * @return	bool	连接成功返回true,否则返回false
	 */
	public function addKey(string $tabName,string $key): bool
	{
		$keys=$this->link->get($tabName);
		if(empty($keys)){
			$keys = [];
		}
		//如果key不存在,就添加一个
		if(!in_array($key, $keys)){
			$keys[]=$key;  //将新的key添加到本表的keys中
			$this->link->set($tabName, $keys);
			return true;   //不存在返回true
		}else{
			return false;  //存在返回false
		}
	}
	
	/**
	 * 向memcache中添加数据
	 *
	 * @param	string	$tabName	需要缓存数据表的表名
	 * @param	string	$sql		使用sql作为memcache的key
	 * @param	mixed	$data		需要缓存的数据
	 */
	public function addCache(string $tabName,string $sql,mixed $data): void
	{
		$key=md5($sql);
		//如果不存在
		if($this->addKey($tabName, $key)){
			$this->link->set($key, $data);
		}
	}

	/**
	 * 获取memcahce中保存的数据
	 *
	 * @param	string	$sql	使用SQL的key
	 * @return 	mixed		返回缓存中的数据
	 */
	public function getCache(string $sql): mixed
	{
		$key=md5($sql);
		return $this->link->get($key);
	}
	
	/**
	 * 检查key
	 *
	 * @return	bool 
	 */
	public function hasCache(string $tabName,string $key): bool
	{
		$keys=$this->link->get($tabName);
		if(empty($keys)){
			return false;
		}
		//如果key不存在
		$key=md5($key);
		if(in_array($key, $keys)){
			return true;   //不存在返回true
		}else{
			return false;  //存在返回false
		}
	}

	/**
	 * 删除和同一个表相关的所有缓存
	 *
	 * @param	string	$tabName	数据表的表名
	 */ 
	public function delCache(string $tabName): void
	{
		$keys=$this->link->get($tabName);
		//删除同一个表的所有缓存
		if(!empty($keys)){
			foreach($keys as $key){
				$this->link->del($key); //0 表示立刻删除
			}
		}
		//删除表的所有sql的key
		$this->link->del($tabName, 0); 
	}

	/**
	 * 删除单独一个语句的缓存
	 *
	 * @param	string	$sql 执行的SQL语句
	 */
	public function delone(string $sql): void
	{
		$key=md5($sql);
		$this->link->del($key); //0 表示立刻删除
	}
}
